package org.wak.dialog
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import org.wak.character.AdventureCharacter;
	import org.wak.character.CharactersManager;
	import org.wak.dialog.event.PuzzleActionEvent;
	import org.wak.dialog.modern.ModernDialogController;
	import org.wak.dialog.custom.CustomDialogController;
	import org.wak.dialog.sci.SciDialogController;
	import org.wak.dialog.scumm.ScummDialogController;
	import org.wak.main.AdventureMaster;
	import org.wak.main.AdventureStyle;
	
	/**
	 * Manager of all the dialogs in the adventure. 
	 * 
	 */	
	public class DialogManager extends EventDispatcher
	{
		
		// the adventure style of the game
		private var mAdventureStyle:String = "";
		
		// xml with the settings for the dialog controller .
		private var mDialogSettings:XML = null ;
		
		// Asoc array of dialogs by id.
		private var mDialogsArray:Array = null ;
		
		// layer to draw the dialogs
		private var mDialogsLayer:Sprite = null ;
		
		// specific controller for the dialogs.
		private var mDialogController:IDialogsController = null ;
		
		// local reference to the characters manager
		private var mCharactersMngr:CharactersManager = null	
		
		
		/**
		 * Constructor. 
		 * @param pLayer The DisplayObject layer where the dialogs will be drawn.
		 * @param pAdvStyle the type of the adventure to choose the apropiate interface.
		 */		
		public function DialogManager( pLayer:Sprite, pAdvStyle:String)
		{
			super();
			mAdventureStyle = pAdvStyle ;
			mDialogsLayer = pLayer ;
		}
		
		/**
		 * Loads the dialogs from xml 
		 * @param pXMLItemsDef input xml with the dialogs.
		 * 
		 */		
		public function LoadDialogs(pXMLItemsDef:XML):void
		{
			mDialogsArray = new Array();
			var fNewDialog:AdventureDialog = null;
			for each( var dialog:XML in pXMLItemsDef.Dialog )
			{
				fNewDialog = new AdventureDialog( dialog );
				mDialogsArray[fNewDialog.dialogId] = fNewDialog ;
			}
		}
		
		/**
		 * Initialize the Dialog manager 
		 * 
		 */		
		public function Initialize(pDialogSettings:XML):void
		{
			mCharactersMngr = AdventureMaster.CharactersMngr ;
			mDialogSettings = pDialogSettings ;
			
			mDialogController = CreateDialogController( mAdventureStyle );
			mDialogController.Initialize() ;
			mDialogsLayer.addChild( mDialogController.display );
			mDialogController.addEventListener(PuzzleActionEvent.PUZZLE_ACTION_EVENT, OnTopicAction,false,0,true );
			
		}
		
		private function OnTopicAction(event:PuzzleActionEvent):void
		{
			var fEvent:Event = new PuzzleActionEvent(PuzzleActionEvent.PUZZLE_ACTION_EVENT, event.methodName);
			this.dispatchEvent(fEvent);
		}
		
		private function CreateDialogController(pAdventureStyle:String):IDialogsController
		{
			var fRetValue:IDialogsController = null ;
			
			switch( pAdventureStyle )
			{
				case AdventureStyle.ScummStyle:
				fRetValue = new ScummDialogController(mDialogsLayer, mDialogSettings);
				break ;
				case AdventureStyle.SCIStyle:
				fRetValue = new SciDialogController(mDialogsLayer, mDialogSettings);
				break;
				case AdventureStyle.ModernStyle:
				fRetValue = new ModernDialogController(mDialogsLayer, mDialogSettings);
				break ;				
				case AdventureStyle.CustomStyle:
					fRetValue = new CustomDialogController(mDialogsLayer, mDialogSettings);
					break ;	
			}
			
			return fRetValue ;
			
		}
		
		/**
		 * Makes a character say something. 
		 * @param pCharId The character speaker.
		 * @param pText the text to say.
		 * @param pOnComplete function reference to call when the task is completed.
		 * 
		 */		
		public function CharacterSay(pCharId:String, pText:String, pOnComplete:Function = null):void
		{
			var fChar:AdventureCharacter = mCharactersMngr.GetCharacter(pCharId);
			mDialogController.CharacterSay( fChar, pText,pOnComplete );
		}
		
		/**
		 * Display a dialgo with an information message.
		 * @param pText The message to display.
		 * @param pOnCompleteFunc callback function for when the message display ends.
		 * 
		 */		
		public function DisplayInfo(pText:String, pOnCompleteFunc:Function = null):void
		{
			mDialogController.DisplayInfo(pText,pOnCompleteFunc);
		}
		
		/**
		 * Starts a dialog 
		 * @param pDialogId dialog id to start.
		 * 
		 */		
		public function StartDialog(pDialogId:String):void
		{
			var fStartingDialog:AdventureDialog = mDialogsArray[pDialogId] ;
			
			if(fStartingDialog != null)
				mDialogController.StartDialog(fStartingDialog);
		}
		
		/**
		 * Get an AdvenureDialog by its id. 
		 * @param pDialogId String with dialog id.
		 * @return the AdventureDialog with the id in pDialogId.
		 * 
		 */		
		public function GetDialog(pDialogId:String):AdventureDialog
		{
			var fRetDialog:AdventureDialog = mDialogsArray[pDialogId] as AdventureDialog ;
			
			if( fRetDialog == null )
			{
				throw new Error("Unknown dialog id: "+ pDialogId);
			}
			
			return fRetDialog ;
		}
		
		public function SetOptionVisible(pDialogId:String, pTopicId:String, value:Boolean):void
		{
			mDialogController.SetOptionVisible(pDialogId, pTopicId, true);
		}
		
		public function UpdateScroll():void
		{
			mDialogController.UpdateScrollButtons();
		}
		

	}
}